# from flask_socketio import emit, join_room, leave_room
from time import sleep, ctime

from apps import socketio
from threading import Lock

from apps.GPS.gpsService import save_gps
from apps.gpsAndPathUtils import analysisPathID, recordGpsAndPath
from apps.trailer.trailerService import get_all_trailer_id, modify_state_by_trailer_id, get_state_by_trailer_id
from flask import request, session, copy_current_request_context
from flask_socketio import SocketIO, emit, join_room, leave_room, \
    close_room, rooms, disconnect


thread = None
thread_lock = Lock()


class TrailerState:
    def __init__(self, trailer_id):
        self.trailer_id = trailer_id
        self.last_received = False      # 默认模拟app上次没有收到服务器发送的事件
        self.state = 2                  # 默认拖车状态是离线的


# 从数据库获取所有拖车的ID
trailer_ids = get_all_trailer_id()
# 初始化拖车状态列表
trailer_state_list = {trailer_id: TrailerState(trailer_id) for trailer_id in trailer_ids}


# def state_callback(trailer_id, state, gps, path_id):
def state_callback(*data):
    print(data)
    if len(data) == 0:
        return
    data = data[0]
    trailer_id = data['trailer_id']
    state = data['state']
    gps = data['gps']
    path_id = data['path_id']
    global trailer_state_list
    trailer_state_list[trailer_id].last_received = True
    trailer_state_list[trailer_id].state = state
    # 向前端发送Gps数据和状态
    socketio.emit(trailer_id + "front", {
        "trailer_ID": trailer_id,
        "path_id": path_id,
        "GPS": gps,
        "state": state
    })
    print({
        "trailer_ID": trailer_id,
        "path_id": path_id,
        "GPS": gps,
        "state": state
    })
    # gps存入数据库
    save_gps(path_id, gps)
    # 状态存入数据库
    modify_state_by_trailer_id(trailer_id, state)


# 状态监控
def state_monitor():
    global trailer_state_list
    while True:
        print(ctime())
        for trailer_state_key in trailer_state_list:
            # trailer_state = trailer_state_list[trailer_state_key]
            trailer_state_list[trailer_state_key].last_received = False
            socketio.emit(trailer_state_list[trailer_state_key].trailer_id+"app", callback=state_callback)
            # # 以下用于检测状态为断线
            # if not trailer_state_list[trailer_state_key].last_received:
            #     # 查数据库，查看其状态是否是在线
            #     state = get_state_by_trailer_id(trailer_state_list[trailer_state_key].trailer_id)
            #     if state == 1:
            #         trailer_state_list[trailer_state_key].state = 0
            #         socketio.emit(trailer_state_list[trailer_state_key].trailer_id + "front", {
            #             "trailer_ID": trailer_state_list[trailer_state_key].trailer_id,
            #             "path_id": "",
            #             "GPS": [],
            #             "state": 0,
            #             "msg": '断线检测'
            #         })
            #         print("发送了断线消息")
            #         modify_state_by_trailer_id(trailer_state_list[trailer_state_key].trailer_id, 0)
        socketio.sleep(5)


def state_monitor_thread():
    global thread
    global thread_lock
    with thread_lock:
        if thread is None:
            thread = socketio.start_background_task(state_monitor)

# # GPS数据入数据库 更新对应的path数据
# # 此函数完成了socketIO接受GPS信息、入队操作以及记录数据库GPS点的作用
# # 如果这是一条新路径，则需要记录开始时间和更新当前的点，以及当前时间
# @socketio.event
# def enQueueAndUpdateDB(message):
#
#     GPS1 = message['gps1']
#     GPS2 = message['gps2']
#     path_ID = message['path_ID']
#     timeStr, trailerID, timeTypeStr = analysisPathID(path_ID)
#     for user in global_dict:                        # 遍历字典
#         if user.has_key(trailerID):                 # 判断各个中控台是否有这个trailer
#             user.get(trailerID).put((GPS1, GPS2))   # 以元组的方式入各个中控台的队
#     recordGpsAndPath(GPS1, GPS2, path_ID)           # 记录GPS和path（一个点） 进入gps表 此时应该思考path
#
#
# def background_thread():
#     """Example of how to send server generated events to clients."""
#     count = 0
#     while True:
#         socketio.sleep(10)
#         count += 1
#         socketio.emit('my_response',
#                       {'data': 'Server generated event', 'count': count})
#
#
# @socketio.event
# def my_event(message):
#     session['receive_count'] = session.get('receive_count', 0) + 1
#     print('data11:', message['gps1'])
#     emit('my_response',
#          {'data': message['gps1'], 'count': session['receive_count']})
#     #
#     print(session)
#
#
# @socketio.event
# def my_broadcast_event(message):
#     session['receive_count'] = session.get('receive_count', 0) + 1
#     emit('my_response',
#          {'data': message['data'], 'count': session['receive_count']},
#          broadcast=True)
#
#
# @socketio.event
# def join(message):
#     join_room(message['room'])
#     session['receive_count'] = session.get('receive_count', 0) + 1
#     emit('my_response',
#          {'data': 'In rooms: ' + ', '.join(rooms()),
#           'count': session['receive_count'], 'gps1': '123.12', 'gps2': '234.34'})
#
#
# @socketio.event
# def leave(message):
#     leave_room(message['room'])
#     session['receive_count'] = session.get('receive_count', 0) + 1
#     emit('my_response',
#          {'data': 'In rooms: ' + ', '.join(rooms()),
#           'count': session['receive_count']})
#
#
# @socketio.on('close_room')
# def on_close_room(message):
#     session['receive_count'] = session.get('receive_count', 0) + 1
#     emit('my_response', {'data': 'Room ' + message['room'] + ' is closing.',
#                          'count': session['receive_count']},
#          to=message['room'])
#     close_room(message['room'])
#
#
# @socketio.event
# def my_room_event(message):
#     session['receive_count'] = session.get('receive_count', 0) + 1
#     emit('my_response',
#          {'data': message['data'], 'count': session['receive_count']},
#          to=message['room'])
#
#
# @socketio.event
# def disconnect_request():
#     @copy_current_request_context
#     def can_disconnect():
#         disconnect()
#
#     session['receive_count'] = session.get('receive_count', 0) + 1
#     # for this emit we use a callback function
#     # when the callback function is invoked we know that the message has been
#     # received and it is safe to disconnect
#     emit('my_response',
#          {'data': 'Disconnected!', 'count': session['receive_count']},
#          callback=can_disconnect)
#
#
# @socketio.event
# def my_ping():
#     emit('my_pong')
#
#
# @socketio.event
# def connect():
#     global thread
#     with thread_lock:
#         if thread is None:
#             thread = socketio.start_background_task(background_thread)
#     emit('my_response', {'data': 'Connected', 'count': 0})
#
#
# @socketio.on('disconnect')
# def test_disconnect():
#     print('Client disconnected', request.sid)
#
#
